package com.vita.core1;

import java.util.LinkedList;
import java.util.Queue;

public class Helper {

    // 从三个列表中获取上升目标
    public static Queue<Integer> getUpTargetFromTree(Queue<Integer> list, Queue<Integer> ups, Queue<Integer> dws, int nowFloor) {
        Queue<Integer> upTarget = getUpTarget(list, nowFloor);
        upTarget.addAll(getUpTarget(ups, nowFloor));
        upTarget.addAll(getUpTarget(dws, nowFloor));
        return upTarget;
    }

    // 从三个列表中获取下降目标
    public static Queue<Integer> getDwTargetFromTree(Queue<Integer> list, Queue<Integer> ups, Queue<Integer> dws, int nowFloor) {
        Queue<Integer> upTarget = getDwTarget(list, nowFloor);
        upTarget.addAll(getDwTarget(ups, nowFloor));
        upTarget.addAll(getDwTarget(dws, nowFloor));
        return upTarget;
    }

    // 从一个列表中获取上升目标
    public static Queue<Integer> getUpTarget(Queue<Integer> q, int nowFloor) {
        Queue<Integer> targets = new LinkedList<>();
        if (!q.isEmpty()) {
            for (int i : q) {
                synchronized ("") {
                    if (i > nowFloor) {
                        targets.add(i);
                    }
                }
            }
        }
        return targets;
    }

    // 从一个列表中获取下降目标
    public static Queue<Integer> getDwTarget(Queue<Integer> q, int nowFloor) {
        Queue<Integer> targets = new LinkedList<>();
        if (!q.isEmpty()) {
            for (int i : q) {
                if (i < nowFloor) {
                    targets.add(i);
                }
            }
        }
        return targets;
    }

    // 从两个目标列表中对比最小距离值，以判断向上还是向下走
    public static int setState(Queue<Integer> ups, Queue<Integer> dws, int nowFloor) {
        // 向上的最小绝对值大一些，就向下走
        if (ups.isEmpty()) {
            return -1;
        }
        if (dws.isEmpty()) {
            return 1;
        }
        if (abs(ups, nowFloor) > abs(dws, nowFloor)) {
            return -1;
        } else if (abs(ups, nowFloor) < abs(dws, nowFloor)) {
            return 1;
        } else {
            return 0;
        }
    }

    // 得到最小绝对值
    private static int abs(Queue<Integer> q, int nowFloor) {
        // 旧绝对值
        int value = 0;
        for (int i : q) {
            // 新绝对值
            int newValue = Math.abs(nowFloor - i);
            // 获得最小的绝对值和对应的楼层
            if (value == 0 || newValue < value) {
                value = newValue;
            }
        }
        return value;
    }

    // 改变确定上下行方向
    public static int checkState(Schedul schedul, int nowFloor, Queue<Integer> list) {
        Queue<Integer> upList = schedul.getUpList();
        Queue<Integer> dwList = schedul.getDwList();
        // 上行目标（可能为空）
        Queue<Integer> newUps = Helper.getUpTargetFromTree(list, upList, dwList, nowFloor);
        // 下行目标（可能为空）
        Queue<Integer> newDws = Helper.getDwTargetFromTree(list, upList, dwList, nowFloor);

        // 当前目标唯一时，改变上下行方向或静止
        if (newUps.size() == 1 && newDws.size()>=1) {
            // 如果已有上行
            if (upOne(schedul, newUps)) {
                if(newDws.size() == 1){
                    // 如果已有下行
                    if(dwOne(schedul, newDws)){
                        return 0;
                    }
                }
                if (list.isEmpty() && upList.isEmpty() && dwList.isEmpty()) {
                    return 0;
                }
                return -1;
            }
        } else if (newDws.size() == 1 && newUps.size() >= 1) {
            // 如果已有下行
            if (dwOne(schedul, newDws)) {
                // 如果已有上行
                if (upOne(schedul, newUps)){
                    return 0;
                }
                if (list.isEmpty() && upList.isEmpty() && dwList.isEmpty()) {
                    return 0;
                }
                return 1;
            }
        }

        // 根据最短距离获取是上行还是下行
        return Helper.setState(newUps, newDws, nowFloor);
    }

    // 返回true条件：有其他机器正在往上走
    private static boolean upOne(Schedul schedul, Queue<Integer> list) {
        Elevator[] es = schedul.getEs();
        for (Elevator e : es) {
            if (e.getState() == 1) {
                Integer lp = list.poll();
                if (lp == null) {
                    return false;
                }
                // 判断是否已走过
                if (e.getNowFloor() < lp) {
                    return true;
                }
            }

        }
        return false;
    }

    // 确定是否当前方向唯一，并已被其他机器抢先消费
    private static boolean dwOne(Schedul schedul, Queue<Integer> list) {
        Elevator[] es = schedul.getEs();
        for (Elevator e : es) {
            if (e.getState() == -1) {
                Integer lp = list.poll();
                if (lp == null) {
                    return false;
                }
                if (e.getNowFloor() > lp) {
                    return true;
                }
            }
        }
        return false;
    }
}
